// ------------------------------------------------------------------------------------------
// Licensed by Interprise Solutions.
// http://www.InterpriseSolutions.com
// For details on this license please visit  the product homepage at the URL above.
// THE ABOVE NOTICE MUST REMAIN INTACT.
// ------------------------------------------------------------------------------------------
using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Web;
using System.Data;
using System.Threading;
using System.Web.Caching;
using System.Collections.Generic;
using System.Data.SqlClient;
using InterpriseSuiteEcommerceCommon.Tool;
using InterpriseSuiteEcommerceCommon.DTO;
using System.Linq;

namespace InterpriseSuiteEcommerceCommon
{
    public class EntitySpecs
    {
        public String m_EntityXsl;
        public String m_EntityName;
        public String m_EntityNamePlural; // because english grammar is unpredictable!
        public bool m_HasParentChildRelationship;
        public bool m_HasDisplayOrder;
        public bool m_HasAddress;
        public String m_ObjectName;
        public String m_ObjectNamePlural; // because english grammar is unpredictable!
        public bool m_EntityObjectMappingIs1to1; // specify true for 1:1 Object:Entity mappings (where the Object table is assumed to have an EntityID column therefore)
        public bool m_HasIconPic;
        public bool m_HasMediumPic;
        public bool m_HasLargePic;

        public EntitySpecs(String XslName, String EntityName, String EntityNamePlural, bool HasParentChildRelationship, bool HasDisplayOrder, bool HasAddress, String ObjectName, String ObjectNamePlural, bool EntityObjectMappingIs1to1, bool HasIconPic, bool HasMediumPic, bool HasLargePic)
        {
            m_EntityXsl = XslName;
            m_EntityName = EntityName;
            m_EntityNamePlural = EntityNamePlural;
            m_HasParentChildRelationship = HasParentChildRelationship;
            m_HasDisplayOrder = HasDisplayOrder;
            m_HasAddress = HasAddress;
            m_ObjectName = ObjectName;
            m_ObjectNamePlural = ObjectNamePlural;
            m_EntityObjectMappingIs1to1 = EntityObjectMappingIs1to1;
            m_HasIconPic = HasIconPic;
            m_HasMediumPic = HasMediumPic;
            m_HasLargePic = HasLargePic;
        }
    }

    public class EntityDefinitions
    {

        static public readonly EntitySpecs readonly_CategoryEntitySpecs = new EntitySpecs("EntityMgr", "Category", "Categories", true, true, false, "Product", "Products", false, true, true, true);
        //static public readonly EntitySpecs readonly_SectionEntitySpecs = new EntitySpecs("EntityMgr", "Section", "Sections", true, true, false, "Product", "Products", false, true, true, true);
        static public readonly EntitySpecs readonly_SectionEntitySpecs = new EntitySpecs("EntityMgr", "Department", "Departments", true, true, false, "Product", "Products", false, true, true, true);
        static public readonly EntitySpecs readonly_ManufacturerEntitySpecs = new EntitySpecs("EntityMgr", "Manufacturer", "Manufacturers", false, true, true, "Product", "Products", true, true, true, true);
        static public readonly EntitySpecs readonly_AttributeEntitySpecs = new EntitySpecs("EntityMgr", "Attribute", "Attributes", false, true, true, "Product", "Products", true, true, true, true);        

        static public EntitySpecs LookupSpecs(String EntityName)
        {
            switch (EntityName.ToUpperInvariant())
            {
                case "CATEGORY":
                    return readonly_CategoryEntitySpecs;
                //case "SECTION":
                case "DEPARTMENT":
                    return readonly_SectionEntitySpecs;
                case "MANUFACTURER":
                    return readonly_ManufacturerEntitySpecs;
                case "ATTRIBUTE":
                    return readonly_AttributeEntitySpecs;
            }
            return null;
        }

    }

    /// <summary>
    /// Summary description for  EntityHelper is a common set of routines that support
    /// a multi level table Parent-child table structure. Note that NOT ALL ROUTINES are semantically valid with all entity types!
    /// </summary>
    public class EntityHelper
    {
        private EntitySpecs m_EntitySpecs;
        private string m_TableName;
        private string m_NodeName;
        private string m_IDColumnName;
        private string m_CacheName;
        private int m_CacheMinutes;
        private string m_XmlPackageName;
        private bool m_OnlyPublishedEntitiesAndObjects;

        // this is public, use with CARE! Make sure you know how this object works before using it!
        public HierarchicalTableMgr m_TblMgr;

        public EntityHelper(EntitySpecs eSpecs)
            : this(AppLogic.CacheDurationMinutes(), eSpecs)
        { }

        public EntityHelper(int CacheMinutes, EntitySpecs eSpecs)
            : this(CacheMinutes, eSpecs, false)
        {
        }
        public EntityHelper(int CacheMinutes, EntitySpecs eSpecs, bool PublishedOnly)
        {
            m_EntitySpecs = eSpecs;
            m_TableName = m_EntitySpecs.m_EntityName;
            m_NodeName = m_EntitySpecs.m_EntityName;
            m_IDColumnName = m_EntitySpecs.m_EntityName + "ID";
            m_CacheName = m_EntitySpecs.m_EntityName + "Mgr";
            m_XmlPackageName = m_EntitySpecs.m_EntityName + "Mgr";
            if (AppLogic.CachingOn)
            {
                m_CacheMinutes = CacheMinutes;
            }
            else
            {
                m_CacheMinutes = 0;
            }
            m_OnlyPublishedEntitiesAndObjects = PublishedOnly;
            m_TblMgr = new HierarchicalTableMgr(m_EntitySpecs.m_EntityName, "Entity", "EntityID", "Name", m_EntitySpecs.m_EntityXsl, m_CacheMinutes, 0, m_OnlyPublishedEntitiesAndObjects);
        }

        public EntitySpecs GetEntitySpecs
        {
            get
            {
                return m_EntitySpecs;
            }
        }

        public string GetEntityYahooSiteMap(string ForParentEntityID, String LocaleSetting, bool AllowCaching, bool RecurseChildren)
        {
            string CacheName = String.Format("GetEntityYahooSiteMap_{0}_{1}_{2}_{3}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), LocaleSetting, RecurseChildren.ToString());
            bool CachingOn = AllowCaching && AppLogic.CachingOn && m_CacheMinutes != 0 && ForParentEntityID.Length != 0;
            if (CachingOn) // just cache the root one
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            string StoreLoc = AppLogic.GetStoreHTTPLocation(false);

            StringWriter tmpS = new StringWriter();
            String XslFile = "EntityYahooSiteMap";
            string XslFilePath = CommonLogic.SafeMapPath("EntityHelper/" + XslFile + ".xslt");
            var xForm = CachingFactory.ApplicationCachingEngineInstance.GetItem<XslCompiledTransform>(XslFilePath);
            if (xForm == null)
            {
                xForm = new XslCompiledTransform(false);
                xForm.Load(XslFilePath);
                CachingFactory.ApplicationCachingEngineInstance.AddItem(XslFilePath, xForm, new CacheDependency(XslFilePath));
            }

            XsltArgumentList xslArgs = new XsltArgumentList();
            xslArgs.AddParam("entity", "", m_EntitySpecs.m_EntityName);
            xslArgs.AddParam("ForParentEntityID", "", ForParentEntityID);
            xslArgs.AddParam("StoreLoc", "", StoreLoc);
            xForm.Transform(m_TblMgr.XmlDoc, xslArgs, tmpS);
            if (AppLogic.AppConfigBool("XmlPackage.DumpTransform"))
            {
                try // don't let logging crash the site
                {
                    StreamWriter sw = File.CreateText(CommonLogic.SafeMapPath(String.Format("images/{0}_{1}_{2}.xfrm.xml", XslFile, m_EntitySpecs.m_EntityName, "store")));
                    sw.WriteLine(XmlCommon.PrettyPrintXml(tmpS.ToString()));
                    sw.Close();
                }
                catch { }
            }

            if (CachingOn)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        public string GetEntityYahooObjectList(string EntityID, string LocaleSetting, string AffiliateID, string CustomerLevelID)
        {
            string CacheName = String.Format("GetEntityYahooObjectList_{0}_{1}_{2}_{3}", EntityID.ToString(), LocaleSetting, AffiliateID.ToString(), CustomerLevelID.ToString());
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string s = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (s != null) { return s; }
            }

            string StoreLoc = AppLogic.GetStoreHTTPLocation(false);
            var tmpS = new StringBuilder(1000);
            string sql = GetListProductsSQL(EntityID, AffiliateID, CustomerLevelID, true, true, false);
            string XslFile = "EntityYahooObjectList";
            string XslFilePath = CommonLogic.SafeMapPath("EntityHelper/" + XslFile + ".xslt");
            var xForm = CachingFactory.ApplicationCachingEngineInstance.GetItem<XslCompiledTransform>(XslFilePath);
            if (xForm == null)
            {
                xForm = new XslCompiledTransform(false);
                xForm.Load(XslFilePath);
                CachingFactory.ApplicationCachingEngineInstance.AddItem(XslFilePath, xForm, new CacheDependency(XslFilePath));
            }

            XsltArgumentList xslArgs = new XsltArgumentList();
            xslArgs.AddParam("entityPrefix", "", m_EntitySpecs.m_EntityName.Substring(0, 1).ToLowerInvariant());
            xslArgs.AddParam("objectPrefix", "", m_EntitySpecs.m_ObjectName.Substring(0, 1).ToLowerInvariant());
            xslArgs.AddParam("storeBaseUrl", "", StoreLoc);
            xslArgs.AddParam("EntityID", "", EntityID.ToString());

            string objXml = string.Empty;
            int rows = DB.GetXml(sql, "root", "object", ref objXml);
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(objXml);
            MemoryStream ms = new MemoryStream();

            xForm.Transform(xdoc, xslArgs, ms);
            ms.Position = 0;
            StreamReader sr = new StreamReader(ms);
            string m_FinalResult = sr.ReadToEnd();
            ms.Close();
            sr.Dispose();
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, m_FinalResult, AppLogic.CacheDurationMinutes());
            }
            return m_FinalResult;
        }
      
        public string GetEntitySelectList(string ForParentEntityID, string Prefix, string FilterEntityID, string LocaleSetting, bool AllowCaching)
        {
            string CacheName = string.Format("GetEntitySelectList_{0}_{1}_{2}_{3}_{4}_{5}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), Prefix, FilterEntityID.ToString(), LocaleSetting, "false");
            bool CachingOn = AllowCaching && AppLogic.CachingOn && m_CacheMinutes != 0; 
            if (CachingOn) // just cache the root one
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            var tmpS = new StringWriter();
            string XslFile = "EntitySelectList";
            string XslFilePath = CommonLogic.SafeMapPath("EntityHelper/" + XslFile + ".xslt");
            var xForm = CachingFactory.ApplicationCachingEngineInstance.GetItem<XslCompiledTransform>(XslFilePath);
            if (xForm == null)
            {
                xForm = new XslCompiledTransform(false);
                xForm.Load(XslFilePath);
                CachingFactory.ApplicationCachingEngineInstance.AddItem(XslFilePath, xForm, new CacheDependency(XslFilePath));
            }
            XsltArgumentList xslArgs = new XsltArgumentList();
            xslArgs.AddParam("ForParentEntityID", "", ForParentEntityID);
            xslArgs.AddParam("filterID", "", FilterEntityID);
            xslArgs.AddParam("custlocale", "", LocaleSetting);
            xslArgs.AddParam("deflocale", "", Localization.WebConfigLocale);
            xslArgs.AddParam("adminsite", "", false);
            xForm.Transform(m_TblMgr.XmlDoc, xslArgs, tmpS);
            if (AppLogic.AppConfigBool("XmlPackage.DumpTransform"))
            {
                try // don't let logging crash the site
                {
                    StreamWriter sw = File.CreateText(CommonLogic.SafeMapPath(String.Format("images/{0}_{1}_{2}.xfrm.xml", XslFile, m_EntitySpecs.m_EntityName, "store")));
                    sw.WriteLine(XmlCommon.PrettyPrintXml(tmpS.ToString()));
                    sw.Close();
                }
                catch { }
            }

            if (CachingOn)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        public string GetListProductsSQL(string EntityInstanceID, string AffiliateID, string CustomerLevelID, bool AllowKits, bool AllowPacks, bool OrderByLooks)
        {
            string OneVariantSQL = string.Empty;
            string FilterSQL = string.Empty;
            string OrderBySQL = string.Empty;
            string FinalSQL = string.Format("exec eCommerceGetSimpleObjectEntityList @EntityCode={0}, @WebSiteCode={1}, @LanguageCode={2}", DB.SQuote(m_EntitySpecs.m_EntityName), DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode), DB.SQuote(Customer.Current.LanguageCode));

            if (EntityInstanceID.Length != 0)
            {
                FinalSQL += ", @EntityID=" + EntityInstanceID;
            }

            if (AppLogic.AppConfigBool("Filter" + m_EntitySpecs.m_ObjectName + "sByAffiliate"))
            {
                FinalSQL += ", @AffiliateCode=" + AffiliateID;
            }
            FinalSQL += ", @PublishedOnly=1";

            if (OrderByLooks)
            {
                FinalSQL += ", @OrderByLooks=1";
            }

            return FinalSQL;
        }

        public string GetEntityULList(string ForParentEntityID, string LocaleSetting, string AffiliateID, string CustomerLevelID, bool AllowCaching, bool IncludeObjects, bool IncludeLinks, String CssClassName, bool RecurseChildren, string OnlyExpandForThisChildID, string Prefix)
        {
            string CacheName = string.Format("GetEntityULList_{0}_{1}_{2}_{3}_{4}_{5}_{6}_{7}_{8}_{9}_{10}_{11}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), LocaleSetting, "false", IncludeObjects, IncludeLinks, CssClassName, RecurseChildren.ToString(), OnlyExpandForThisChildID.ToString(), Prefix, AffiliateID.ToString(), CustomerLevelID.ToString());
            bool CachingOn = AllowCaching && AppLogic.CachingOn && m_CacheMinutes != 0 && ForParentEntityID.Length == 0;

            if (CachingOn) // just cache the root one
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            XmlDocument xdoc = new XmlDocument();
            if (IncludeObjects)
            {
                string sql = GetListProductsSQL(String.Empty, AffiliateID, CustomerLevelID, true, true, false);
                string xml = String.Empty;
                int rows = DB.GetXml(sql, "objects", "object", ref xml);
                xdoc.LoadXml(m_TblMgr.XmlDoc.InnerXml.Replace("</root>", xml + "</root>"));
            }
            else
            {
                if (m_TblMgr.XmlDoc.InnerXml.Length != 0)
                {
                    xdoc.LoadXml(m_TblMgr.XmlDoc.InnerXml);
                }
            }

            Prefix = Prefix + Prefix;
            var tmpS = new StringWriter();
            string XslFile = "EntityULList";
            string XslFilePath = CommonLogic.SafeMapPath("EntityHelper/" + XslFile + ".xslt");
            var xForm = CachingFactory.ApplicationCachingEngineInstance.GetItem<XslCompiledTransform>(XslFilePath);
            if (xForm == null)
            {
                xForm = new XslCompiledTransform(false);
                xForm.Load(XslFilePath);
                CachingFactory.ApplicationCachingEngineInstance.AddItem(XslFilePath, xForm, new CacheDependency(XslFilePath));
            }
            XsltArgumentList xslArgs = new XsltArgumentList();

            XSLTExtensions ExtObj = new XSLTExtensions(Customer.Current, Customer.Current.SkinID);
            xslArgs.AddExtensionObject("urn:ise", ExtObj);

            xslArgs.AddParam("entity", "", m_EntitySpecs.m_EntityName);
            xslArgs.AddParam("ForParentEntityID", "", ForParentEntityID);
            xslArgs.AddParam("IncludeLinks", "", IncludeLinks);
            xslArgs.AddParam("AffiliateID", "", AffiliateID);
            xslArgs.AddParam("IncludeObjects", "", IncludeObjects);
            xslArgs.AddParam("CssClassName", "", CssClassName);
            xslArgs.AddParam("RecurseChildren", "", RecurseChildren);
            xslArgs.AddParam("OnlyExpandForThisChildID", "", OnlyExpandForThisChildID);
            xslArgs.AddParam("Prefix", "", Prefix);
            xslArgs.AddParam("custlocale", "", LocaleSetting);
            xslArgs.AddParam("deflocale", "", Localization.WebConfigLocale);
            xslArgs.AddParam("adminsite", "", false);
            xslArgs.AddParam("objName", "", m_EntitySpecs.m_ObjectName.ToLowerInvariant());
            xForm.Transform(xdoc, xslArgs, tmpS);
            if (AppLogic.AppConfigBool("XmlPackage.DumpTransform"))
            {
                try // don't let logging crash the site
                {
                    StreamWriter sw = File.CreateText(CommonLogic.SafeMapPath(String.Format("images/{0}_{1}_{2}.xfrm.xml", XslFile, m_EntitySpecs.m_EntityName, "store")));
                    sw.WriteLine(XmlCommon.PrettyPrintXml(tmpS.ToString()));
                    sw.Close();
                }
                catch { }
            }

            if (CachingOn)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        public string GetEntityULListPhone(int ForParentEntityID, string LocaleSetting, int AffiliateID, int CustomerLevelID, bool AllowCaching, bool IncludeObjects, bool IncludeLinks, String CssClassName, bool RecurseChildren, int OnlyExpandForThisChildID, string Prefix, string IGD)
        {
            string CacheName = string.Format("GetEntityULListPhone_{0}_{1}_{2}_{3}_{4}_{5}_{6}_{7}_{8}_{9}_{10}_{11}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), LocaleSetting, false, IncludeObjects, IncludeLinks, CssClassName, RecurseChildren.ToString(), OnlyExpandForThisChildID.ToString(), Prefix, AffiliateID.ToString(), CustomerLevelID.ToString());
            bool CachingOn = AllowCaching && AppLogic.CachingOn && m_CacheMinutes != 0 && ForParentEntityID == 0;

            if (CachingOn) // just cache the root one
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            XmlDocument xdoc = new XmlDocument();
            if (IncludeObjects)
            {
                string sql = string.Empty; 
                string xml = String.Empty;
                int rows = DB.GetXml(sql, "objects", "object", ref xml);
                xdoc.LoadXml(m_TblMgr.XmlDoc.InnerXml.Replace("</root>", xml + "</root>"));
            }
            else
            {
                if (m_TblMgr.XmlDoc.InnerXml.Length != 0)
                {
                    xdoc.LoadXml(m_TblMgr.XmlDoc.InnerXml);
                }
            }

            Prefix = Prefix + Prefix;
            var tmpS = new StringWriter();
            string XslFile = "EntityULListPhone";
            string XslFilePath = CommonLogic.SafeMapPath("EntityHelper/" + XslFile + ".xslt");
            var xForm = CachingFactory.ApplicationCachingEngineInstance.GetItem<XslCompiledTransform>(XslFilePath);
            if (xForm == null)
            {
                xForm = new XslCompiledTransform(false);
                xForm.Load(XslFilePath);
                CachingFactory.ApplicationCachingEngineInstance.AddItem(XslFilePath, xForm, new CacheDependency(XslFilePath));
            }
            XsltArgumentList xslArgs = new XsltArgumentList();
            xslArgs.AddParam("entity", "", m_EntitySpecs.m_EntityName);
            xslArgs.AddParam("ForParentEntityID", "", ForParentEntityID);
            xslArgs.AddParam("IncludeLinks", "", IncludeLinks);
            xslArgs.AddParam("AffiliateID", "", AffiliateID);
            xslArgs.AddParam("IncludeObjects", "", IncludeObjects);
            xslArgs.AddParam("CssClassName", "", CssClassName);
            xslArgs.AddParam("RecurseChildren", "", RecurseChildren);
            xslArgs.AddParam("OnlyExpandForThisChildID", "", OnlyExpandForThisChildID);
            xslArgs.AddParam("Prefix", "", Prefix);
            xslArgs.AddParam("custlocale", "", LocaleSetting);
            xslArgs.AddParam("deflocale", "", Localization.WebConfigLocale);
            xslArgs.AddParam("adminsite", "", false);
            xslArgs.AddParam("objName", "", m_EntitySpecs.m_ObjectName.ToLowerInvariant());
            xslArgs.AddParam("IGD", "", IGD);
            xForm.Transform(xdoc, xslArgs, tmpS);
            if (AppLogic.AppConfigBool("XmlPackage.DumpTransform"))
            {
                try // don't let logging crash the site
                {
                    StreamWriter sw = File.CreateText(CommonLogic.SafeMapPath(String.Format("{images/{0}_{1}_{2}.xfrm.xml", XslFile, m_EntitySpecs.m_EntityName, "store")));
                    sw.WriteLine(XmlCommon.PrettyPrintXml(tmpS.ToString()));
                    sw.Close();
                }
                catch { }
            }

            if (CachingOn)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();

        }

        public String GetEntityComponentArtNode(String ForParentEntityID, String LocaleSetting, String AffiliateID, String CustomerLevelID, bool AllowCaching, bool ShowObjects)
        {
            String CacheName = String.Format("GetEntityComponentArtNode_{0}_{1}_{2}_{3}_{4}_{5}_{6}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), LocaleSetting, "false", ShowObjects.ToString(), AffiliateID.ToString(), CustomerLevelID.ToString());
            bool CachingOn = AllowCaching && AppLogic.CachingOn && m_CacheMinutes != 0 && ForParentEntityID.Length == 0;
            if (CachingOn) // just cache the root one
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            StringBuilder tmpS = new StringBuilder(4096);

            XmlNode n;
            if (ForParentEntityID.Length == 0)
            {
                n = m_TblMgr.ResetToRootNode();
            }
            else
            {
                n = m_TblMgr.SetContext(ForParentEntityID);
            }

            if (n != null && m_TblMgr.HasChildren(n))
            {
                n = m_TblMgr.MoveFirstChild(n);
                while (n != null)
                {
                    String ThisID = m_TblMgr.CurrentID(n);
                    String URL = String.Empty;
                    URL = String.Format(SE.MakeEntityLink(m_EntitySpecs.m_EntityName, ThisID, m_TblMgr.CurrentField(n, "SEName")));
                    if (CommonLogic.IsStringNullOrEmpty(XmlCommon.XmlEncodeAttribute(m_TblMgr.CurrentFieldByLocale(n, "Description", LocaleSetting))))
                    {
                        tmpS.Append("<node Text=\"" + XmlCommon.XmlEncodeAttribute(m_TblMgr.CurrentName(n, LocaleSetting)) + "\" NavigateUrl=\"" + XmlCommon.XmlEncodeAttribute(URL) + "\">\n");
                    }
                    else
                    {
                        tmpS.Append("<node Text=\"" + XmlCommon.XmlEncodeAttribute(m_TblMgr.CurrentFieldByLocale(n, "Description", LocaleSetting)) + "\" NavigateUrl=\"" + XmlCommon.XmlEncodeAttribute(URL) + "\">\n");
                    }
                    
                    if (ShowObjects)
                    {
                        tmpS.Append(GetEntityComponentArtObjectList(ThisID, LocaleSetting, AffiliateID, CustomerLevelID));
                    }
                    if (m_TblMgr.HasChildren(n))
                    {
                        tmpS.Append(GetEntityComponentArtNode(ThisID, LocaleSetting, AffiliateID, CustomerLevelID, AllowCaching, ShowObjects));
                    }
                    tmpS.Append("</node>");
                    n = m_TblMgr.MoveNextSibling(n, false);
                }
            }
            if (CachingOn)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        public String GetEntityGoogleSiteMap(String ForParentEntityID, String LocaleSetting, bool AllowCaching, bool RecurseChildren)
        {
            String CacheName = String.Format("GetEntityGoogleSiteMap_{0}_{1}_{2}_{3}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), LocaleSetting, RecurseChildren.ToString());
            bool CachingOn = AllowCaching && AppLogic.CachingOn && m_CacheMinutes != 0 && ForParentEntityID.Length != 0;
            if (CachingOn) // just cache the root one
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            var tmpS = new StringWriter();
            string StoreLoc = AppLogic.GetStoreHTTPLocation(false);
            string XslFile = "EntityGoogleSiteMap";
            string XslFilePath = CommonLogic.SafeMapPath("EntityHelper/" + XslFile + ".xslt");
            var xForm = CachingFactory.ApplicationCachingEngineInstance.GetItem<XslCompiledTransform>(XslFilePath);
            if (xForm == null)
            {
                xForm = new XslCompiledTransform(false);
                xForm.Load(XslFilePath);
                CachingFactory.ApplicationCachingEngineInstance.AddItem(XslFilePath, xForm, new CacheDependency(XslFilePath));
            }
            XsltArgumentList xslArgs = new XsltArgumentList();
            xslArgs.AddParam("entity", "", m_EntitySpecs.m_EntityName);
            xslArgs.AddParam("ForParentEntityID", "", ForParentEntityID);
            xslArgs.AddParam("StoreLoc", "", StoreLoc);
            xForm.Transform(m_TblMgr.XmlDoc, xslArgs, tmpS);
            if (AppLogic.AppConfigBool("XmlPackage.DumpTransform"))
            {
                try // don't let logging crash the site
                {
                    StreamWriter sw = File.CreateText(CommonLogic.SafeMapPath(String.Format("images/{0}_{1}_{2}.xfrm.xml", XslFile, m_EntitySpecs.m_EntityName, "store")));
                    sw.WriteLine(XmlCommon.PrettyPrintXml(tmpS.ToString()));
                    sw.Close();
                }
                catch { }
            }

            if (CachingOn)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        private string GetEntityULObjectList(string EntityID, string LocaleSetting, string AffiliateID, string CustomerLevelID, bool IncludeLinks, string CssClassName)
        {
            string CacheName = string.Format("GetEntityULObjectList_{0}_{1}_{2}_{3}_{4}_{5}", EntityID.ToString(), LocaleSetting, IncludeLinks, CssClassName, AffiliateID.ToString(), CustomerLevelID.ToString());
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string s = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (s != null) { return s; }
            }

            var tmpS = new StringBuilder(1000);
            string sql = GetListProductsSQL(EntityID, AffiliateID, CustomerLevelID, true, true, false);
            var ds = DB.GetDS(sql, true, System.DateTime.Now.AddMinutes(AppLogic.CacheDurationMinutes()));
            if (ds.Tables[0].Rows.Count > 0)
            {
                if (CssClassName.Length != 0)
                {
                    tmpS.Append(String.Format("<ul class=\"{0}\">", CssClassName));
                }
                else
                {
                    tmpS.Append("<ul>");
                }
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    tmpS.Append("<li>");
                    if (IncludeLinks)
                    {
                        tmpS.Append("<a href=\"" + SE.MakeObjectAndEntityLink(m_EntitySpecs.m_ObjectName, m_EntitySpecs.m_EntityName, DB.RowField(row, "ObjectID"), EntityID, DB.RowField(row, "SEName")) + "\">");
                     }
                    tmpS.Append(HttpContext.Current.Server.HtmlEncode(DB.RowFieldByLocale(row, "Name", LocaleSetting)));
                    if (IncludeLinks)
                    {
                        tmpS.Append("</a>");
                    }
                    tmpS.Append("</li>");
                }
                tmpS.Append("</ul>");
            }
            ds.Dispose();

            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }

            return tmpS.ToString();
        }

        private string GetEntityComponentArtObjectList(String EntityID, String LocaleSetting, String AffiliateID, String CustomerLevelID)
        {
            string CacheName = String.Format("GetEntityComponentArtObjectList_{0}_{1}_{2}_{3}", EntityID.ToString(), LocaleSetting, AffiliateID.ToString(), CustomerLevelID.ToString());
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string s = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (s != null) { return s; }
            }

            StringBuilder tmpS = new StringBuilder(1000);
            String sql = GetListProductsSQL(EntityID, AffiliateID, CustomerLevelID, true, true, false);
            DataSet ds = DB.GetDS(sql, true, System.DateTime.Now.AddMinutes(AppLogic.CacheDurationMinutes()));
            if (ds.Tables[0].Rows.Count > 0)
            {
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    string itemName = string.Empty;
                    String URL = String.Empty;
                    if (!CommonLogic.IsStringNullOrEmpty(DB.RowField(row, "ItemDescription").ToString()))
                    {
                        itemName = DB.RowField(row, "ItemDescription");
                    }
                    else
                    {
                        itemName = DB.RowField(row, "ItemName");
                    }
                    URL = SE.MakeObjectAndEntityLink(m_EntitySpecs.m_ObjectName, m_EntitySpecs.m_EntityName, DB.RowField(row, "ObjectID"), EntityID, itemName);
                    tmpS.Append("<node Text=\"" + XmlCommon.XmlEncodeAttribute(itemName) + "\" NavigateUrl=\"" + XmlCommon.XmlEncodeAttribute(URL) + "\" />\n");
                }
            }
            ds.Dispose();

            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }

            return tmpS.ToString();
        }

        public String GetEntityGoogleObjectList(String EntityID, String LocaleSetting, String AffiliateID, String CustomerLevelID)
        {
            String CacheName = String.Format("GetEntityGoogleObjectList_{0}_{1}_{2}_{3}", EntityID.ToString(), LocaleSetting, AffiliateID.ToString(), CustomerLevelID.ToString());
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string s = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (s != null) { return s; }
            }

            String StoreLoc = AppLogic.GetStoreHTTPLocation(false);
            StringBuilder tmpS = new StringBuilder(1000);
            String sql = GetListProductsSQL(EntityID, AffiliateID, CustomerLevelID, true, true, false);
            DataSet ds = DB.GetDS(sql, true, System.DateTime.Now.AddMinutes(AppLogic.CacheDurationMinutes()));
            if (ds.Tables[0].Rows.Count > 0)
            {
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    tmpS.Append("<url>");
                    tmpS.Append("<loc>" + StoreLoc + SE.MakeObjectAndEntityLink(m_EntitySpecs.m_ObjectName, m_EntitySpecs.m_EntityName, DB.RowField(row, "ObjectID"), EntityID, DB.RowField(row, "SEName")) + "</loc> ");
                    tmpS.Append("<changefreq>" + AppLogic.AppConfig("GoogleSiteMap.ObjectChangeFreq") + "</changefreq> ");
                    tmpS.Append("<priority>" + AppLogic.AppConfig("GoogleSiteMap.ObjectPriority") + "</priority> ");
                    tmpS.Append("</url>");
                }
            }
            ds.Dispose();

            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }

            return tmpS.ToString();
        }

        public String GetParentEntity(String EntityID)
        {
            String tmp = String.Empty;
            if (EntityID.Length != 0)
            {
                XmlNode n = m_TblMgr.SetContext(EntityID);
                if (n != null)
                {
                    n = m_TblMgr.MoveParent(n);
                    if (n != null)
                    {
                        tmp = m_TblMgr.CurrentID(n);
                    }
                }
            }
            return tmp;
        }

        public String GetRootEntity(String RootOrSubEntityID)
        {
            String tmp = String.Empty;
            if (RootOrSubEntityID.Length != 0)
            {
                XmlNode n = m_TblMgr.SetContext(RootOrSubEntityID);
                while (n != null && !m_TblMgr.IsRootLevel(n))
                {
                    n = m_TblMgr.MoveParent(n);
                }
                tmp = m_TblMgr.CurrentID(n);
            }
            return tmp;
        }

        public String GetEntityBrowseBox(int SkinID, String LocaleSetting)
        {
            String CacheName = String.Format("GetEntityBrowseBox_{0}_{1}_{2}_{3}", m_EntitySpecs.m_EntityName, SkinID.ToString(), LocaleSetting, "false");
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu == null) { return Menu; }
            }

            StringBuilder tmpS = new StringBuilder(10000);

            XmlNode n = m_TblMgr.SetContextToFirstRootLevelNode();
            bool anyFound = false;
            if (n != null)
            {
                tmpS.Append("<table cellpadding=\"2\" cellspacing=\"0\" border=\"0\" style=\"border-style: solid; border-width: 0px; border-color: #" + AppLogic.AppConfig("HeaderBGColor") + "\">\n");
                tmpS.Append("<tr><td align=\"left\" valign=\"top\">\n");
                tmpS.Append("<img src=\"" + AppLogic.LocateImageURL("skins/Skin_" + SkinID.ToString() + "/images/browseby" + m_EntitySpecs.m_EntityName + ".gif") + "\" border=\"0\" /><br />");
                tmpS.Append("<table width=\"100%\" cellpadding=\"4\" cellspacing=\"0\" border=\"0\" style=\"" + AppLogic.AppConfig("BoxFrameStyle") + "\">\n");
                tmpS.Append("<tr><td align=\"left\" valign=\"top\">\n");

                //Converted to Objects to get the list of IDs for 1 time query
                var entityItems = GetEntityModelListFromXML(LocaleSetting);
                anyFound = (entityItems.Count() > 0);

                //Get all ids that has No SEName
                var listId = entityItems.Where(i => i.SEName == string.Empty)
                                        .Select(i => i.Counter)
                                        .ToArray();

                var lst = new List<KeyValuePair<string, string>>();
                //get the list of links from the ids if atleast 1 No Sename.
                if (listId.Count() > 0) { lst = SE.GetEntitySENameLinkList(m_EntitySpecs.m_EntityName, listId).ToList(); }

                foreach (var item in entityItems)
                {
                    //Conditional Statement to determine the sename value;
                    string LinkValue = string.Empty;
                    if (item.SEName != string.Empty)
                    {
                        LinkValue = SE.MakeEntityLink(m_EntitySpecs.m_EntityName, item.Counter, item.SEName);
                    }
                    else
                    {
                        LinkValue = lst.FirstOrDefault(i => i.Key == item.Counter).Value;
                    }

                    tmpS.AppendFormat("<img height=\"8\" src=\"{0}\" />&nbsp;<a href=\"{1}\">{2}</a><br/>",
                        AppLogic.LocateImageURL(string.Format("skins/skin_{0}/images/redarrow.gif", SkinID)), LinkValue, item.NameLocale);
                }

                tmpS.Append("</td></tr>\n");
                tmpS.Append("</table>\n");
                tmpS.Append("</td></tr>\n");
                tmpS.Append("</table>\n");
            }

            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }

            return CommonLogic.IIF(anyFound, tmpS.ToString(), string.Empty);
        }

        //Extract Counter, EntityName, SEName, NameLocale
        public IEnumerable<EntityModel> GetEntityModelListFromXML(string LocaleSetting)
        {
            var n = m_TblMgr.SetContextToFirstRootLevelNode();
            var lst = new List<EntityModel>();
            while (n != null)
            {
                lst.Add(new EntityModel(){
                    Counter = m_TblMgr.CurrentID(n),
                    EntityName = m_EntitySpecs.m_EntityName,
                    SEName = m_TblMgr.CurrentField(n, "SEName"),
                    NameLocale = m_TblMgr.CurrentName(n, LocaleSetting)
                });
                n = m_TblMgr.MoveNextSibling(n, false);
            }
            return lst;
        }

        public String GetEntityName(String EntityID, String LocaleSetting)
        {
            String tmp = String.Empty;
            if (EntityID.Length != 0)
            {
                XmlNode n = m_TblMgr.SetContext(EntityID);
                if (n != null)
                {
                    tmp = m_TblMgr.CurrentFieldByLocale(n, "Name", LocaleSetting);
                }
            }
            return tmp;
        }

        public String GetEntityField(String EntityID, String Field, String LocaleSetting)
        {
            String tmp = String.Empty;
            if (EntityID.Length != 0)
            {
                XmlNode n = m_TblMgr.SetContext(EntityID);
                if (n != null)
                {
                    tmp = m_TblMgr.CurrentFieldByLocale(n, Field, LocaleSetting);
                }
            }
            return tmp;
        }

        public String OpenCubeMenu(String ForParentEntityID, int SkinID, String LocaleSetting)
        {
            String CacheName = String.Format("OpenCubeMenu{0}_{1}_{2}_{3}_{4}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), SkinID.ToString(), LocaleSetting, "false");
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            StringBuilder tmpS = new StringBuilder(4096);

            XmlNode n;
            if (ForParentEntityID.Length == 0)
            {
                n = m_TblMgr.ResetToRootNode();
            }
            else
            {
                n = m_TblMgr.SetContext(ForParentEntityID);
            }

            if (ForParentEntityID.Length == 0 && !m_TblMgr.HasChildren(n))
            {
                // NO ENTITIES IN THE DB, RETURN EMPTY STRING
            }
            else
            {
                if (ForParentEntityID.Length == 0)
                {
                    tmpS.Append("<li style=\"width:110px;\"><a href=\"#\">(!AppConfig." + m_EntitySpecs.m_EntityName + "PromptPlural!)</a>\n");
                }
                if (n != null && m_TblMgr.HasChildren(n))
                {
                    if (ForParentEntityID.Length == 0)
                    {
                        tmpS.Append("<div><ul style=\"width:140px;top:0px;left:0px;\"><div>\n");
                    }
                    else
                    {
                        tmpS.Append("<div><ul style=\"width:140px;top:-18px;left:135px;\"><div>\n");
                    }
                    n = m_TblMgr.MoveFirstChild(n);
                    while (n != null)
                    {
                        String ThisID = m_TblMgr.CurrentID(n);
                        String URL = String.Empty;
                        URL = SE.MakeEntityLink(m_EntitySpecs.m_EntityName, ThisID, "");
                        tmpS.Append("<li><a href=\"" + XmlCommon.XmlEncodeAttribute(URL) + "\">" + m_TblMgr.CurrentName(n, Thread.CurrentThread.CurrentUICulture.Name) + "</a>\n");
                        if (!AppLogic.AppConfigBool("Limit" + m_EntitySpecs.m_EntityName + "MenuToOneLevel") && m_TblMgr.HasChildren(n))
                        {
                            tmpS.Append(OpenCubeMenu(ThisID, SkinID, LocaleSetting));
                        }
                        n = m_TblMgr.MoveNextSibling(n, false);
                    }
                    tmpS.Append("</div></ul></div>\n");
                }
                if (ForParentEntityID.Length == 0)
                {
                    tmpS.Append("</li>\n");
                }
            }

            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        public String OpenCubeMenuVertical(String ForParentEntityID, int SkinID, String LocaleSetting)
        {
            String CacheName = String.Format("OpenCubeMenuVertical{0}_{1}_{2}_{3}_{4}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), SkinID.ToString(), LocaleSetting, "false");
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            StringBuilder tmpS = new StringBuilder(4096);

            XmlNode n;
            if (ForParentEntityID.Length == 0)
            {
                n = m_TblMgr.ResetToRootNode();
            }
            else
            {
                n = m_TblMgr.SetContext(ForParentEntityID);
            }

            if (ForParentEntityID.Length == 0 && !m_TblMgr.HasChildren(n))
            {
                // NO ENTITIES IN THE DB, RETURN EMPTY STRING
            }
            else
            {
                if (ForParentEntityID.Length == 0)
                {
                    tmpS.Append("<li style=\"width:175px;\"><a href=\"#\">(!AppConfig." + m_EntitySpecs.m_EntityName + "PromptPlural!)</a>\n");
                }
                if (n != null && m_TblMgr.HasChildren(n))
                {
                    if (ForParentEntityID.Length == 0)
                    {
                        tmpS.Append("<div><ul style=\"width:175px;top:-20px;left:173px;\"><div>\n");
                    }
                    else
                    {
                        tmpS.Append("<div><ul style=\"width:175px;top:-20px;left:173px;\"><div>\n");
                    }
                    n = m_TblMgr.MoveFirstChild(n);
                    while (n != null)
                    {
                        String ThisID = m_TblMgr.CurrentID(n);
                        String URL = String.Empty;
                        URL = SE.MakeEntityLink(m_EntitySpecs.m_EntityName, ThisID, "");
                        tmpS.Append("<li><a href=\"" + XmlCommon.XmlEncodeAttribute(URL) + "\">" + m_TblMgr.CurrentName(n, Thread.CurrentThread.CurrentUICulture.Name) + "</a>\n");
                        if (!AppLogic.AppConfigBool("Limit" + m_EntitySpecs.m_EntityName + "MenuToOneLevel") && m_TblMgr.HasChildren(n))
                        {
                            tmpS.Append(OpenCubeMenuVertical(ThisID, SkinID, LocaleSetting));
                        }
                        n = m_TblMgr.MoveNextSibling(n, false);
                    }
                    tmpS.Append("</div></ul></div>\n");
                }
                if (ForParentEntityID.Length == 0)
                {
                    tmpS.Append("</li>\n");
                }
            }

            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        public String ComponentArtTree(String ForParentEntityID, int SkinID, String LocaleSetting, String SelectedID)
        {
            String CacheName = String.Format("ComponentArtTree_{0}_{1}_{2}_{3}_{4}_{5}", m_EntitySpecs.m_EntityName, ForParentEntityID.ToString(), SkinID.ToString(), LocaleSetting, "false", SelectedID.ToString());
            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            StringWriter tmpS = new StringWriter();

            if (m_TblMgr.XmlDoc.SelectNodes("//Entity").Count != 0)
            {
                String XslFile = "ComponentArtTree";
                XslCompiledTransform xForm;
                string XslFilePath = CommonLogic.SafeMapPath("EntityHelper/" + XslFile + ".xslt");
                xForm = CachingFactory.ApplicationCachingEngineInstance.GetItem<XslCompiledTransform>(XslFilePath);
                if (xForm == null)
                {
                    xForm = new XslCompiledTransform(false);
                    xForm.Load(XslFilePath);
                    CachingFactory.ApplicationCachingEngineInstance.AddItem(XslFilePath, xForm, new CacheDependency(XslFilePath));
                }
                XsltArgumentList xslArgs = new XsltArgumentList();
                xslArgs.AddParam("entity", "", m_EntitySpecs.m_EntityName);
                xslArgs.AddParam("ForParentEntityID", "", ForParentEntityID);
                xslArgs.AddParam("entityDispName", "", XmlCommon.XmlEncodeAttribute(AppLogic.GetString("AppConfig." + m_EntitySpecs.m_EntityName + "PromptPlural", SkinID, LocaleSetting)));
                xslArgs.AddParam("adminsite", "", false);
                xslArgs.AddParam("custlocale", "", LocaleSetting);
                xslArgs.AddParam("deflocale", "", Localization.WebConfigLocale);
                xslArgs.AddParam("expandID", "", SelectedID);
                xForm.Transform(m_TblMgr.XmlDoc, xslArgs, tmpS);
                if (AppLogic.AppConfigBool("XmlPackage.DumpTransform"))
                {
                    try // don't let logging crash the site
                    {
                        StreamWriter sw = File.CreateText(CommonLogic.SafeMapPath(String.Format("images/{0}_{1}_{2}.xfrm.xml", XslFile, m_EntitySpecs.m_EntityName, "store")));
                        sw.WriteLine(XmlCommon.PrettyPrintXml(tmpS.ToString()));
                        sw.Close();
                    }
                    catch { }
                }
            }

            if (AppLogic.CachingOn && m_CacheMinutes != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();

        }

        public String GetListForStyleBrowser(String PackID, String ForParentEntityID, bool isFull)
        {
            String CacheName = String.Format("GetListForStyleBrowser_{0}_{1}_{2}_{3}_{4}", m_EntitySpecs.m_EntityName, PackID.ToString(), ForParentEntityID.ToString(), isFull.ToString(), "false");
            if (AppLogic.CachingOn && m_CacheMinutes != 0 && ForParentEntityID.Length != 0)
            {
                string Menu = CachingFactory.ApplicationCachingEngineInstance.GetItem<string>(CacheName);
                if (Menu != null) { return Menu; }
            }

            StringBuilder tmpS = new StringBuilder(4096);

            XmlNode n;
            if (ForParentEntityID.Length == 0)
            {
                n = m_TblMgr.ResetToRootNode();
            }
            else
            {
                n = m_TblMgr.SetContext(ForParentEntityID);
            }

            if (n != null && m_TblMgr.HasChildren(n))
            {
                n = m_TblMgr.MoveFirstChild(n);
                while (n != null)
                {
                    String ThisID = m_TblMgr.CurrentID(n);
                    tmpS.Append("<span class=\"SBCatName\">" + m_TblMgr.CurrentName(n, Thread.CurrentThread.CurrentUICulture.Name).ToUpper() + "</span><br />");

                    using (SqlConnection con = DB.NewSqlConnection())
                    {
                        con.Open();
                        using (IDataReader rsp = DB.GetRSFormat(con, "Select * from (" + m_EntitySpecs.m_ObjectName + " with (NOLOCK) left outer join Product" + m_EntitySpecs.m_EntityName + " pe with (NOLOCK) on " + m_EntitySpecs.m_ObjectName + "." + m_EntitySpecs.m_ObjectName + "ID= pe." + m_EntitySpecs.m_ObjectName + "ID) where pe." + m_IDColumnName + "=" + ThisID.ToString() + " and Deleted=0 " + CommonLogic.IIF(m_OnlyPublishedEntitiesAndObjects, "and Published=1", "") + " and ShowIn" + m_EntitySpecs.m_ObjectName + "Browser=1 and IsAPack=0 and IsAKit=0 order by DisplayOrder,Name"))
                        {
                            while (rsp.Read())
                            {
                                String ProdURL = "pb.aspx?type=" + CommonLogic.QueryStringCanBeDangerousContent("type") + "&PackID=" + PackID.ToString() + "&" + m_EntitySpecs.m_ObjectName + "ID=" + DB.RSFieldInt(rsp, "ProductID").ToString() + "&" + m_IDColumnName + "=" + ThisID.ToString() + "&isfull=" + isFull.ToString();
                                tmpS.Append("&nbsp;&nbsp;<a class=\"SBProdName\" href=\"" + ProdURL + "\" target=\"pb\">" + DB.RSFieldByLocale(rsp, "Name", Thread.CurrentThread.CurrentUICulture.Name) + "</a><br />");
                            }
                        }
                    }

                    if (m_TblMgr.HasChildren(n))
                    {
                        tmpS.Append(GetListForStyleBrowser(PackID, ThisID, isFull));
                    }
                    n = m_TblMgr.MoveNextSibling(n, false);
                }
            }

            if (AppLogic.CachingOn && m_CacheMinutes != 0 && ForParentEntityID.Length != 0)
            {
                CachingFactory.ApplicationCachingEngineInstance.AddItem(CacheName, tmpS.ToString(), AppLogic.CacheDurationMinutes());
            }
            return tmpS.ToString();
        }

        public int GetNumEntityObjects(String EntityID, bool includeKits, bool includePacks)
        {
            String tmpSQLString = String.Empty;
            //If EntityID is empty put -100 as default value to prevent error. 
            //Not sure why sometimes it gets empty string.
            if (EntityID.Trim() == "")
            {
                EntityID = "-100";
            }
            switch (m_EntitySpecs.m_EntityName)
            {
                case "Category":
                    tmpSQLString = "select Count(*) as N from InventoryItem A with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " inner join InventoryCategory B with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " on A.ItemCode = B.ItemCode ";
                    tmpSQLString = tmpSQLString + " inner join systemCategory C with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " on C.CategoryCode = B.CategoryCode ";
                    tmpSQLString = tmpSQLString + " inner join InventoryItemWebOption D with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " on A.ItemCode = D.ItemCode AND D.Published=1 and D.WebSiteCode =" + DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode) + " ";
                    tmpSQLString = tmpSQLString + " inner join systemCategoryWebOption E with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " on C.CategoryCode = E.CategoryCode AND E.Published=1 and E.WebSiteCode =" + DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode) + " ";
                    tmpSQLString = tmpSQLString + " where C.Counter = " + EntityID.ToString() + " AND D.CheckOutOption=0 ";
                    tmpSQLString = tmpSQLString + " and A.ItemType IN ('Stock', 'Kit', 'Matrix Group', 'Non-Stock', 'Electronic Download', 'Service', 'Assembly')";
                    break;

                case "Department":
                    tmpSQLString = "SELECT COUNT(*) AS N FROM InventoryItem II with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " INNER JOIN InventoryItemDepartment IID with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " ON II.ItemCode = IID.ItemCode ";
                    tmpSQLString = tmpSQLString + " INNER JOIN InventorySellingDepartment ISD with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " ON ISD.DepartmentCode = IID.DepartmentCode ";
                    tmpSQLString = tmpSQLString + " INNER JOIN InventoryItemWebOption IIW with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " ON II.ItemCode = IIW.ItemCode AND IIW.Published = 1 AND IIW.WebSiteCode=" + DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode) + " ";
                    tmpSQLString = tmpSQLString + " INNER JOIN InventorySellingDepartmentWebOption ISDW with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " ON ISD.DepartmentCode = ISDW.DepartmentCode AND ISDW.Published = 1 AND ISDW.WebSiteCode=" + DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode) + " ";
                    tmpSQLString = tmpSQLString + " WHERE ISD.Counter=" + EntityID.ToString() + " AND IIW.CheckOutOption=0 ";
                    tmpSQLString = tmpSQLString + " AND II.ItemType IN ('Stock', 'Kit', 'Matrix Group', 'Non-Stock', 'Electronic Download', 'Service', 'Assembly')";
                    break;

                case "Manufacturer":
                    tmpSQLString = "SELECT COUNT(*) AS N FROM InventoryItem II with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " INNER JOIN SystemManufacturer SM with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " ON II.ManufacturerCode = SM.ManufacturerCode ";
                    tmpSQLString = tmpSQLString + " INNER JOIN InventoryItemWebOption IIW with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " ON II.ItemCode = IIW.ItemCode AND IIW.Published = 1 AND IIW.WebSiteCode=" + DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode) + " ";
                    tmpSQLString = tmpSQLString + " INNER JOIN SystemManufacturerWebOption SMW with (NOLOCK) ";
                    tmpSQLString = tmpSQLString + " ON SM.ManufacturerCode = SMW.ManufacturerCode AND SMW.Published = 1 AND SMW.WebSiteCode=" + DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode) + " ";
                    tmpSQLString = tmpSQLString + " WHERE II.ManufacturerCode = ";
                    tmpSQLString = tmpSQLString + " (SELECT ManufacturerCode FROM SystemManufacturer with (NOLOCK) WHERE Counter=" + EntityID.ToString() + ") AND IIW.CheckOutOption=0 ";
                    tmpSQLString = tmpSQLString + " AND II.ItemType IN ('Stock', 'Kit', 'Matrix Group', 'Non-Stock', 'Electronic Download', 'Service', 'Assembly')";
                    break;
                case "Attribute":                    
                    string LastViewedEntityInstanceName = CommonLogic.CookieCanBeDangerousContent("LastViewedEntityInstanceName", true);
                    if (LastViewedEntityInstanceName.Length > 0)
                    {
                        tmpSQLString = string.Format("SELECT COUNT(*) AS N FROM InventoryItemAttributeView WHERE AttributeValue = '{0}' AND LanguageCode = '{1}'", LastViewedEntityInstanceName, Customer.Current.LanguageCode);
                    }
                    else
                    {
                        return 0;
                    }
                    break;
            }
            return DB.GetSqlN(tmpSQLString);
        }

        public String GetAdvancedEntityBrowseBox(Customer ThisCustomer, int SkinID)
        {
            String VisibleNodeID = CommonLogic.QueryStringCanBeDangerousContent(m_IDColumnName);
            String s = m_EntitySpecs.m_EntityName.ToUpperInvariant();
            if (VisibleNodeID.Length == 0 && 
                ("CATEGORY".Equals(m_EntitySpecs.m_EntityName, StringComparison.InvariantCultureIgnoreCase) || 
                "DEPARTMENT".Equals(m_EntitySpecs.m_EntityName, StringComparison.InvariantCultureIgnoreCase) || 
                "LIBRARY".Equals(m_EntitySpecs.m_EntityName, StringComparison.InvariantCultureIgnoreCase)))
            {
                String ObjectID = CommonLogic.QueryStringCanBeDangerousContent(m_EntitySpecs.m_ObjectName + "ID");
                if (ObjectID.Length != 0)
                {
                    String[] ents = GetObjectEntities(ObjectID, false).Split(','); ;
                    if (ents.Length > 0)
                    {
                        try
                        {
                            VisibleNodeID = ents[0];
                        }
                        catch { }
                    }
                }
            }
            StringBuilder tmpS = new StringBuilder(4096);
            tmpS.Append("<div id=\"vertmenustyle1\">");
            tmpS.Append(this.GetEntityULList(Convert.ToString(0), ThisCustomer.LocaleSetting, ThisCustomer.AffiliateID, string.Empty, true, false, true, "sitemapul", false, VisibleNodeID, "&nbsp;&nbsp;"));
            tmpS.Append("</div>");
            return tmpS.ToString();
        }

        public String GetObjectEntities(String ObjectID, bool ForObjectBrowser)
        {
            StringBuilder sql = new StringBuilder();
            switch (m_IDColumnName.ToLower())
            {
                case "categoryid":
                    sql.Append("select C.Counter as CategoryID from InventoryItem A with (NOLOCK) ");
                    sql.Append(" inner join InventoryCategory B with (NOLOCK) ");
                    sql.Append(" on A.ItemCode = B.ItemCode ");
                    sql.Append(" inner join systemCategory C with (NOLOCK) ");
                    sql.Append(" on C.CategoryCode = B.CategoryCode ");
                    sql.Append(" where C.ParentCategory IN (select categorycode from systemCategoryWebOption with (NOLOCK) where published=1 and ");
                    sql.Append(DB.SQuote(Localization.DateTimeStringForDB(DateTime.Now)) + " between isnull(StartDate, '1/1/1900') and isnull(EndDate, '12/31/9999')) ");
                    sql.Append(" and A.ItemCode = " + DB.SQuote(ObjectID.ToString()));
                    break;
                case "departmentid":
                    sql.Append("select C.Counter AS DepartmentID from InventoryItem A with (NOLOCK) ");
                    sql.Append(" inner join InventoryItemDepartment B with (NOLOCK) ");
                    sql.Append(" on A.ItemCode = B.ItemCode ");
                    sql.Append(" inner join InventorySellingDepartment C with (NOLOCK) ");
                    sql.Append(" on B.DepartmentCode = C.DepartmentCode ");
                    sql.Append(" where C.ParentDepartment IN (select departmentcode from inventorySellingDepartmentWebOption with (NOLOCK) where published=1 and ");
                    sql.Append(DB.SQuote(Localization.DateTimeStringForDB(DateTime.Now)) + " between isnull(StartDate, '1/1/1900') and isnull(EndDate, '12/31/9999')) ");
                    sql.Append(" and A.ItemCode = " + DB.SQuote(ObjectID.ToString()));
                    break;
                case "manufacturerid":
                    sql.Append("Select B.Counter as ManufacturerID from InventoryItem A with (NOLOCK) ");
                    sql.Append(" inner join systemManufacturer B with (NOLOCK) ");
                    sql.Append(" on A.ManufacturerCode = B.ManufacturerCode ");
                    sql.Append(" where B.ManufacturerCode IN (select manufacturercode from systemManufacturerWebOption with (NOLOCK) where published=1 and ");
                    sql.Append(DB.SQuote(Localization.DateTimeStringForDB(DateTime.Now)) + " between isnull(StartDate, '1/1/1900') and isnull(EndDate, '12/31/9999')) ");
                    sql.Append(" and A.ItemCode = " + DB.SQuote(ObjectID.ToString()));
                    break;
                default:
                    break;
            }

            StringBuilder tmpS = new StringBuilder(1000);

            using (SqlConnection con = DB.NewSqlConnection())
            {
                con.Open();
                using (IDataReader rs = DB.GetRSFormat(con, sql.ToString()))
                {
                    while (rs.Read())
                    {
                        if (tmpS.Length != 0)
                        {
                            tmpS.Append(",");
                        }
                        tmpS.Append(DB.RSFieldInt(rs, m_IDColumnName).ToString());
                    }
                }
            }

            return tmpS.ToString();
        }

        public static ArrayList GetProductEntityList(String itemCode, String EntityName)
        {
            ArrayList al = new ArrayList();
            if (EntityName.Length == 0)
            {
                EntityName = EntityDefinitions.readonly_CategoryEntitySpecs.m_EntityName;
            }

            using (DataSet ds = DB.GetDS(string.Format("exec eCommerceGetProductEntityList @ItemCode = {0}, @EntityName = {1}, @WebSiteCode = {2}, @LanguageCode = {3}", DB.SQuote(itemCode), DB.SQuote(EntityName), DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode), DB.SQuote(Customer.Current.LanguageCode)), false, System.DateTime.Now.AddMinutes(AppLogic.CacheDurationMinutes())))
            {
                if (ds.Tables[0].Rows.Count > 0)
                {
                    foreach (DataRow row in ds.Tables[0].Rows)
                    {
                        al.Add(DB.RowFieldInt(row, EntityName + "ID"));
                    }
                }
            }

            return al;
        }

        public static int GetProductsFirstEntity(String itemCode, String EntityName)
        {
            int tmp = 0;
            if (EntityName.Length == 0)
            {
                EntityName = EntityDefinitions.readonly_CategoryEntitySpecs.m_EntityName;
            }

            using (SqlConnection con = DB.NewSqlConnection())
            {
                con.Open();
                using (IDataReader rs = DB.GetRSFormat(con, "exec eCommerceGetProductsFirstEntity @ItemCode = {0}, @EntityName = {1}, @WebSiteCode = {2}", DB.SQuote(itemCode), DB.SQuote(EntityName), DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode)))
                {
                    if (rs.Read())
                    {
                        tmp = DB.RSFieldInt(rs, EntityName + "ID");
                    }
                }
            }

            return tmp;
        }

        public String GetCurrentEntityID()
        {
            String VisibleNodeID = CommonLogic.QueryStringCanBeDangerousContent(m_IDColumnName);            
            if (VisibleNodeID.Length == 0 &&
                ("CATEGORY".Equals(m_EntitySpecs.m_EntityName, StringComparison.InvariantCultureIgnoreCase) ||
                "DEPARTMENT".Equals(m_EntitySpecs.m_EntityName, StringComparison.InvariantCultureIgnoreCase) ||
                "LIBRARY".Equals(m_EntitySpecs.m_EntityName, StringComparison.InvariantCultureIgnoreCase)))
            {
                String ObjectID = CommonLogic.QueryStringCanBeDangerousContent(m_EntitySpecs.m_ObjectName + "ID");
                if (ObjectID.Length != 0)
                {
                    String[] ents = GetObjectEntities(ObjectID, false).Split(','); ;
                    if (ents.Length > 0)
                    {
                        try
                        {
                            VisibleNodeID = ents[0];
                        }
                        catch { }
                    }
                }
            }
            return VisibleNodeID;
        }

    }
}